package domain.server;

import domain.Commands;
import domain.GameSettings;
import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 *
 * @author Laurent Albessart
 * @version 31-dec-2011
 */
public class S19Server implements Runnable {

    private static final int PORT = 56565;
    private DatagramSocket datagramSocket;
    private JTextArea textArea;
    private PlayerModel clientModel;

    public S19Server() {

        JFrame infoFrame = new JFrame();
        infoFrame.setLayout(new BorderLayout());

        textArea = new JTextArea();
        textArea.setEditable(false);

        infoFrame.add(new JScrollPane(textArea), BorderLayout.CENTER);

        infoFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        infoFrame.setSize(350, 500);
        infoFrame.setVisible(true);

        writeHostMessage("Opening port " + PORT + ".");

        try {

            datagramSocket = new DatagramSocket(PORT);
            writeHostMessage("\nPort " + PORT + " is opened.");

        } catch (SocketException ex) {

            writeHostMessage("\nFailed to open port " + PORT + ".");
            writeHostMessage("\nPlease make sure port " + PORT + " is open.");

        }

    }

    @Override
    public void run() {

        if (datagramSocket != null) {
            {
                BufferedReader in = null;
                try {
                    //Getting external IP address
                    URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp");
                    in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
                    String ip = in.readLine();

                    //TODO initialise EVERYTHING! map, items, ...

                    //Make the model which has all the clients
                    clientModel = new PlayerModel(datagramSocket);


                    writeHostMessage("\nHosting on " + ip + ":" + PORT);
                    writeHostMessage("\nThe server is now accepting connections.");

                    //TODO actually accepting messages
                    String msgIn;

                    byte[] buffer;
                    DatagramPacket inPacket;

                    while (!datagramSocket.isClosed()) {

                        buffer = new byte[256];
                        inPacket = new DatagramPacket(buffer, buffer.length);
                        datagramSocket.receive(inPacket);

                        writeHostMessage("Received message from client.");

                        handleMessage(inPacket);

                    }


                } catch (IOException ex) {
                    Logger.getLogger(S19Server.class.getName()).log(Level.SEVERE, null, ex);

                    writeHostMessage("\nProblem finding IP.");

                } finally {
                    try {
                        in.close();
                        datagramSocket.close();
                    } catch (IOException ex) {
                        Logger.getLogger(S19Server.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }

        }

    }

    public void handleMessage(DatagramPacket inPacket) {
        System.out.println("Interpret message.");
        String msgIn = new String(inPacket.getData(), 0, inPacket.getLength());
        System.out.println("Message is " + msgIn);
        //throw new UnsupportedOperationException("Not supported yet.");
        String[] commands = msgIn.split(GameSettings.COMMANDSSPLIT);

        for (String msg : commands) {
            Commands command = Commands.valueOf(msg.substring(0, msg.indexOf(GameSettings.SEPARATOR)));
            String line = msg.substring(msg.indexOf(GameSettings.SEPARATOR) + 1);

            switch (command) {
                case JOIN:
                    clientModel.addPlayer(line, new Player(inPacket.getAddress(), inPacket.getPort()));
                    break;
                case LEAVE:
                    clientModel.removePlayer(line);
                    break;
                case TALK:
                    //TODO add controle
                    clientModel.sendMessageToAllPlayers(Commands.TALK + GameSettings.SEPARATOR + line);
                    break;
                default:
                    //unknown command -> handle!
                    System.out.println("unknown command: " + command);
                    break;
            }
        }
    }

    private void writeHostMessage(String msg) {
        textArea.append(msg);
        System.out.print(msg);
    }
}
